package golf.stockdata.framework.batch;

import golf.stockdata.framework.ability.BatchAbility;
import golf.stockdata.framework.batch.dataobject.Batch;
import golf.stockdata.framework.common.ApplicationConstant;
import golf.stockdata.framework.exception.AbilityInitializationException;

import java.util.Properties;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.apache.log4j.Logger;
import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;

public class SimpleBatchAbility implements BatchAbility {
	
	private static Logger logger = Logger.getLogger(SimpleBatchAbility.class);

	private String batchFile;
	private Batch batchConfiguration;
	private static Scheduler SCHEDULER;
	private static SchedulerFactory SCHEDULER_FACTORY = new org.quartz.impl.StdSchedulerFactory();

	public void initializeAbility(Properties props)
			throws AbilityInitializationException {
		
		logger.debug(">>> initializeAbility");
		
		batchFile = props.getProperty("batchFile");
		if (batchFile == null) {
			throw new AbilityInitializationException("batchFile is missing");
		}

		try {
			loadBatchConfiguration();
		} catch (JAXBException e) {
			logger.debug("JAXBException " + e.getErrorCode() + "/"
					+ e.getMessage());
			throw new AbilityInitializationException(e);
		}
		
		logger.debug("<<< initializeAbility");

	}

	public void start() {

		logger.debug(">>> start");

		try {
			
			SCHEDULER = SCHEDULER_FACTORY.getScheduler();
			SCHEDULER.start();
			
			for(golf.stockdata.framework.batch.dataobject.JobData job:batchConfiguration.getJobs()){
				
				JobDataMap dataMap = new JobDataMap();
				dataMap.put(ApplicationConstant.JOB_STEP_DATA, job.getJobStepData());
				JobDetail jobDetail = JobBuilder.newJob(JobProcessor.class)
						.withIdentity(job.getName()).usingJobData(dataMap).build();
				
				Trigger trigger = TriggerBuilder.newTrigger()
						.withSchedule(CronScheduleBuilder.cronSchedule(job.getCronexpression())).build();

				SCHEDULER.scheduleJob(jobDetail, trigger);
			}


			
		} catch (SchedulerException e) {
			logger.error(e);
			if(logger.isDebugEnabled()){
				e.printStackTrace();
			}
		}
		
		logger.debug("<<< start");

	}

	private void loadBatchConfiguration() throws JAXBException {
		
		logger.debug(">>> loadBatchConfiguration");

		JAXBContext context = JAXBContext.newInstance(Batch.class);
		Unmarshaller m = context.createUnmarshaller();
		batchConfiguration = (Batch) m.unmarshal(this.getClass()
				.getClassLoader().getResourceAsStream(batchFile));

		logger.debug("<<< loadBatchConfiguration");
		
	}

	public void destroy() {
		logger.debug(">>> destroy");
		try {
			logger.debug("Shutting down the scheduler");
			SCHEDULER.shutdown();
		} catch (SchedulerException e) {
			logger.warn(e);
			if(logger.isDebugEnabled()){
				e.printStackTrace();
			}
		}
		logger.debug("<<< destroy");
	}

}
